package display3D.scene3D {
	
	import Tools.Geometry;
	
	import alternativa.engine3d.containers.BSPContainer;
	import alternativa.engine3d.containers.DistanceSortContainer;
	import alternativa.engine3d.core.Camera3D;
	import alternativa.engine3d.core.EllipsoidCollider;
	import alternativa.engine3d.core.MipMapping;
	import alternativa.engine3d.core.MouseEvent3D;
	import alternativa.engine3d.core.Object3D;
	import alternativa.engine3d.core.Object3DContainer;
	import alternativa.engine3d.core.View;
	import alternativa.engine3d.materials.FillMaterial;
	import alternativa.engine3d.materials.TextureMaterial;
	import alternativa.engine3d.primitives.Box;
	
	import display3D.controller3D.WalkController;
	
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.filters.GlowFilter;
	import flash.geom.ColorTransform;
	import flash.geom.Vector3D;
	import flash.text.TextField;
	import flash.ui.Keyboard;
	
	import mx.controls.Text;
	import mx.core.UIComponent;
	import display3D.objet3D.Salle3D;
	
	
	/**
	 * Classe gérant l'affiche 3D 
	 * @author Arnaud
	 */
	public class Scene3Da extends UIComponent {
		
		private var _rootContainer:BSPContainer = new BSPContainer();
		
		/**
		 * Objet Alternativa3D représentant notre camera
		 */
		private var camera:Camera3D;
		
		
		/**
		 * Controlleur de la camera3D
		 * @see WalkController
		 */
		var controllerCamera:WalkController; 
		
		private var _currentSalle:Salle3D;
		
		private var _oldSalle:Salle3D;
		
		private var _nextSalle:Salle3D;
		
		public function Scene3Da() 
		{
			addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		/**
		 * Initialise tout les objet nécéssaires à notre scene
		 * @param evt Event.ADDED_TO_STAGE
		 */
		public function init(evt:Event) {
			//Alignement du stage
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
			
			//Creation de la camera et de la vue
			camera = new Camera3D();
			camera.view = new View(stage.stageWidth, stage.stageHeight);
			addChild(camera.view);
			addChild(camera.diagram);
			rootContainer.threshold = 0.06;
			rootContainer.addChild(camera);
			
			// Listeners
			stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
			stage.addEventListener(Event.RESIZE, onResize);
			
			//Creation du controller de la camera
			 controllerCamera = new WalkController(camera,stage,rootContainer);
			 controllerCamera.checkCollision = false;
		}
		
		
		/**
		 * Appelé à chaque image
		 * @param e Event.ENTER_FRAME
		 */
		private function onEnterFrame(e:Event):void 
		{
			//Detecte les oeuvres à proximiter de la camera
			//Detecte les points de transitions
			if (currentSalle!=null && camera!=null)
			{
				detecterOeuvre(camera.x,camera.y,camera.z);
				if (detecterTransition(camera.x,camera.y,camera.z))
				{
					controllerCamera.SPEED = 0;
				}
			}
			camera.render();
		}
		
		/**
		 * Appelé lorsque l'utilisateur redimensionne sa fenêtre de navigation
		 * @param e Event.RESIZE
		 */
		private function onResize(e:Event = null):void {
			camera.view.width = stage.stageWidth;
			camera.view.height = stage.stageHeight;
		}
		
		/**
		 * Fonction qui affiche la salle courante.
		 * </br>
		 * Attention cette fonction ne s'applique que dans le cas ou la salle est affiché depuis le menu
		 */
		public function afficheSalle():void{
			this._currentSalle.draw(rootContainer);
			controllerCamera.startPosition(currentSalle.position_x,currentSalle.position_y);
		}
		
		/**
		 * Affiche la nouvelle salle lors d'une transition
		 * @param porteCible Identifiant de la porte cible de la nouvelle salle
		 */
		public function afficheNext(porteCible:String):void
		{
			//On supprime l'ancienne salle de la scene
			this._oldSalle.supprimerSalle(rootContainer);
			//On desactive la transition pour éviter des chargement en boucle
			this._currentSalle.getPorteById(porteCible).transition.entrer =false;
			//On dessine la nouvelle salle sur la scene
			this._currentSalle.draw(rootContainer);
			//on supprime les transition de l'ancienne salle
			this._oldSalle.supprimerTransition(rootContainer);
			//on supprime l'ancienne salle
			this._oldSalle = null;
			//on ouvre la porte de la nouvelle salle
			this._currentSalle.getPorteById(porteCible).ouvrirPorte();
			this._currentSalle.getPorteById(porteCible).open = true;
			//On reactive la vitesse du walkcontroller
			controllerCamera.SPEED = 20;
		}
		

		/**
		 * Supprime tout ce qui se trouve de la scene hormis la camera la view et le controller
		 */
		public function supprimerTout():void
		{
			currentSalle.supprimerSalle(rootContainer);
			currentSalle.supprimerTransition(rootContainer);
		}
		
		/**
		 * Detecte une oeuvre par rapport à la position de la caméra
		 * @param x Position x de la caméra
		 * @param y	Position y de la caméra
		 * @param z Position z de la caméra
		 */
		public function detecterOeuvre(x:*,y:*,z:*):void
		{
			currentSalle.detecterOeuvre(x,y,z);
		}
		
		/**
		 * Detecte un point de transition par rapport à la position de la caméra
		 * @param x Position x de la caméra
		 * @param y	Position y de la caméra
		 * @param z Position z de la caméra
		 */
		public function detecterTransition(x:*,y:*,z:*):Boolean
		{
			return currentSalle.detecterTransition(x,y,z);
		}

		/**
		 * Objet Alternativa3D représentant notre scene
		 */
		public function get rootContainer():BSPContainer
		{
			return _rootContainer;
		}

		/**
		 * @private
		 */
		public function set rootContainer(value:BSPContainer):void
		{
			_rootContainer = value;
		}

		/**
		 * Salle actuellement affichée
		 */
		public function get currentSalle():Salle3D
		{
			return _currentSalle;
		}

		/**
		 * @private
		 */
		public function set currentSalle(value:Salle3D):void
		{
			_currentSalle = value;
		}

		/**
		 * Salle en attente de destruction
		 */
		public function get oldSalle():Salle3D
		{
			return _oldSalle;
		}

		/**
		 * @private
		 */
		public function set oldSalle(value:Salle3D):void
		{
			_oldSalle = value;
		}

		/**
		 * Salle à affichée
		 */
		public function get nextSalle():Salle3D
		{
			return _nextSalle;
		}

		/**
		 * @private
		 */
		public function set nextSalle(value:Salle3D):void
		{
			_nextSalle = value;
		}


	}
}
